home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / PASCAL / ALLSWAGS.ZIP / SWAGG-M.ZIP / MISC.SWG / 0184_Convert C Header to Pascal.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-08-30  |  30.0 KB  |  1,121 lines

  1. {$A+,B-,F-,G+,I-,P-,Q-,R-,S-,T-,V-,X+,Y+}
  2. Program H2Pas;
  3. { Program:   H2PAS
  4.   Version:   1.21
  5.   Purpose:   convert C header files to some kind of Pascal units
  6.  
  7.   Developer: Peter Sawatzki (ps) (c) 1993
  8.              Buchenhof 3, 58091 Hagen, Germany
  9.  CompuServe: 100031,3002
  10.  
  11.   revision history:
  12.   date       version  author   modification
  13.   11/03/93   1.00     ps       written
  14.   05/10/94   1.10     ps       add EXEHDR import support
  15.   06/29/94   1.2x     ps       minor modifications
  16. }
  17. Uses
  18.   Objects,
  19.   Strings;
  20.  
  21. Const
  22.   Version = 'H2Pas v.1.21';
  23.   H2PasIni= 'H2Pas.Ini';
  24.   CRLF = #13#10;
  25.   StdUses: pChar = 'Uses'+CRLF+
  26.                    '  WinTypes,'+CRLF+
  27.                    '  WinProcs;';
  28.   HasImports: Boolean = False;
  29.   WhichBlock: (Undefd, InConst, InType, InVar, InFunc) = Undefd;
  30. Var
  31.   DstName,
  32.   Imports: String[67];
  33.  
  34.   Function WordCount(aStr, Delims: pChar): Integer;
  35.   Var
  36.     Count: Integer;
  37.     EndStr: pChar;
  38.   Begin
  39.     EndStr:= StrEnd(aStr);
  40.     Count:= 0;
  41.     While aStr<=EndStr Do Begin
  42.       While (aStr<=EndStr) And (StrScan(Delims, aStr[0])<>Nil) Do Inc(aStr);
  43.       If aStr<=EndStr Then Inc(Count);
  44.       While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Inc(aStr)
  45.     End;
  46.     WordCount:= Count
  47.   End;
  48.  
  49.   Function WordPosition (aStr, Delims: pChar; No: Integer): pChar;
  50.   Var
  51.     Count: Integer;
  52.     EndStr: pChar;
  53.   Begin
  54.     EndStr:= StrEnd(aStr);
  55.     Count:= 0;
  56.     WordPosition:= Nil;
  57.     While (aStr<=EndStr) And (Count<>No) Do Begin
  58.       While (aStr<=EndStr) And (StrScan(Delims, aStr[0])<>Nil) Do Inc(aStr);
  59.       If aStr<=EndStr Then Inc(Count);
  60.       If Count<>No Then
  61.         While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Inc(aStr)
  62.       Else
  63.         WordPosition:= aStr
  64.     End
  65.   End;
  66.  
  67.   Function ExtractWord (aDst, aStr, Delims: pChar; No: Integer): pChar;
  68.   Var
  69.     EndStr: pChar;
  70.   Begin
  71.     ExtractWord:= aDst;
  72.     aStr:= WordPosition(aStr, Delims, No);
  73.     If Assigned(aStr) Then Begin
  74.       EndStr:= StrEnd(aStr);
  75.       While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Begin
  76.         aDst[0]:= aStr[0];
  77.         Inc(aStr);
  78.         Inc(aDst)
  79.       End
  80.     End;
  81.     aDst[0]:= #0
  82.   End;
  83.  
  84.   Function Trim (aDst, aSrc: pChar): pChar;
  85.   Var
  86.     EndStr: pChar;
  87.   Begin
  88.     Trim:= aDst;
  89.     If Not Assigned(aSrc) Or (aSrc[0]=#0) Then
  90.       aDst[0]:= #0
  91.     Else Begin
  92.       EndStr:= StrEnd(aSrc);
  93.       While (aSrc<EndStr) And (aSrc[0]<=' ') Do
  94.         Inc(aSrc);
  95.       StrCopy(aDst, aSrc);
  96.       EndStr:= StrEnd(aDst);
  97.       While (EndStr>aDst) And (EndStr[0]<=' ') Do Begin
  98.         EndStr[0]:= #0;
  99.         Dec(EndStr)
  100.       End
  101.     End
  102.   End;
  103.  
  104.   Function Pad (aDst, aSrc: pChar; Count: Integer): pChar;
  105.   Begin
  106.     Pad:= aDst;
  107.     If aDst<>aSrc Then
  108.       StrCopy(aDst, aSrc);
  109.     Count:= Count-StrLen(aDst);
  110.     aDst:= StrEnd(aDst);
  111.     While Count>0 Do Begin
  112.       aDst[0]:= ' ';
  113.       Inc(aDst);
  114.       Dec(Count)
  115.     End;
  116.     aDst[0]:= #0
  117.   End;
  118.  
  119. Function StrIPos(Str1, Str2: PChar): PChar;
  120. Var
  121.   EndStr: pChar;
  122.   Len: Integer;
  123. Begin
  124.   StrIPos:= Nil;
  125.   EndStr:= StrEnd(Str1);
  126.   Len:= StrLen(Str2);
  127.   Repeat
  128.     Str1:= StrScan(Str1, Str2[0]);
  129.     If Str1=Nil Then Exit;
  130.     If StrLIComp(Str1, Str2, Len)=0 Then Begin
  131.       StrIPos:= Str1;
  132.       Exit
  133.     End;
  134.     Inc(Str1)
  135.   Until Str1>EndStr
  136. End;
  137.  
  138.   Function JustFilename(PathName : string) : string;
  139.   {-Return just the filename of a pathname}
  140.   Var
  141.     I: Word;
  142.   Begin
  143.     I:= Succ(Word(Length(PathName)));
  144.     Repeat
  145.       Dec(I);
  146.     Until (PathName[I] in  ['\', ':', #0]) or (I = 0);
  147.     JustFilename := Copy(PathName, Succ(I), 64);
  148.   End;
  149.  
  150.   function JustName(PathName : string) : string;
  151.     {-Return just the name (no extension, no path) of a pathname}
  152.   var
  153.     DotPos : Byte;
  154.   begin
  155.     PathName := JustFileName(PathName);
  156.     DotPos := Pos('.', PathName);
  157.     if DotPos > 0 then
  158.       PathName := Copy(PathName, 1, DotPos-1);
  159.     JustName := PathName;
  160.   end;
  161.  
  162.   Function JustPath(aName: string): string;
  163.   {-Return just the path of a filename}
  164.   Var
  165.     I: Word;
  166.   Begin
  167.     I:= Succ(Word(Length(aName)));
  168.     Repeat
  169.       Dec(I);
  170.     Until (aName[I] in  ['\', ':', #0]) or (I = 0);
  171.     JustPath:= Copy(aName, 1, I)
  172.   End;
  173.  
  174.   Procedure Fatal (aMsg: pChar);
  175.   Begin
  176.     WriteLn(aMsg);
  177.     Halt(255)
  178.   End;
  179.  
  180.   Function GetLine (aDst: pChar; Var aFile: Text): pChar;
  181.   Var
  182.     aString: String;
  183.     p,i: Integer;
  184.   Begin
  185.     {$i-}
  186.     ReadLn(aFile, aString);
  187.     If IoResult<>0 Then Fatal('Read error.');
  188.     p:= Pos('//', aString);
  189.     If p>0 Then Begin
  190.       aString[p+1]:= '*';
  191.       aString:= aString+' */'
  192.     End;
  193.     p:= Pos(#9, aString);
  194.     While p>0 Do Begin
  195.       aString[p]:= ' ';
  196.       For i:= 1 To 7-((p-1) Mod 8) Do
  197.         Insert(' ', aString, p);
  198.       p:= Pos(#9, aString)
  199.     End;
  200.     GetLine:= StrPCopy(aDst, aString)
  201.   End;
  202.  
  203.   Procedure OutLn (Var aFile: Text; OutStr: pChar);
  204.   Var
  205.     oc: Char;
  206.   Begin
  207.     While OutStr[0]<>#0 Do Begin
  208.       oc:= OutStr[0];
  209.       Case oc Of
  210.         '/': If OutStr[1]='*' Then Begin
  211.                oc:= '{';
  212.                Inc(OutStr,1)
  213.              End;
  214.         '*': If OutStr[1]='/' Then Begin
  215.                oc:= '}';
  216.                Inc(OutStr)
  217.              End
  218.       End;
  219.       Write(aFile, oc);
  220.       If IoResult<>0 Then Fatal('Write error.');
  221.       Inc(OutStr)
  222.     End;
  223.     Write(aFile,CRLF);
  224.     If IoResult<>0 Then Fatal('Write error.')
  225.   End;
  226.  
  227. Procedure HeaderInfo (Var aFile: Text);
  228. Var
  229.   aLine: Array[0..100] Of Char;
  230. Begin
  231.   WriteLn(aFile, '{ Unit: ',DstName);
  232.   WriteLn(aFile, '  Version: 1.00');
  233.   WriteLn(aFile, '  translated from file ',DstName,'.H');
  234.   WriteLn(aFile, '  raw translation using '+Version+', (c) Peter Sawatzki');
  235.   WriteLn(aFile, '  fine tuned by:');
  236.   WriteLn(aFile, '    (fill in)');
  237.   WriteLn(aFile, ' ');
  238.   WriteLn(aFile, '  revision history:');
  239.   WriteLn(aFile, '  Date:    Ver: Author: Mod:');
  240.   WriteLn(aFile, '  xx/xx/94 1.00 <name>  <modification>');
  241.   WriteLn(aFile, '}');
  242.   WriteLn(aFile, 'Unit ',DstName,';');
  243.   WriteLn(aFile, 'Interface');
  244.   If StrLen(StdUses)<>0 Then
  245.     WriteLn(aFile, StdUses);
  246. End;
  247.  
  248. {-the collection part}
  249. Type
  250.   pImportEntry = ^tImportEntry;
  251.   tImportEntry = Record
  252.     TheName,
  253.     TheDLL,
  254.     TheOrd: pChar
  255.   End;
  256.   pImportCollection = ^tImportCollection;
  257.   tImportCollection = Object(tSortedCollection)
  258.     Function KeyOf(Item: Pointer): Pointer; Virtual;
  259.     Function Compare(Key1, Key2: Pointer): Integer; Virtual;
  260.     Procedure FreeItem(Item: Pointer); Virtual;
  261.   End;
  262.  
  263.   pTypeMap = ^tTypeMap;
  264.   tTypeMap = Record
  265.     F, T: pChar;
  266.   End;
  267.   pTypeMapCollection = ^tTypeMapCollection;
  268.   tTypeMapCollection = Object(tSortedCollection)
  269.     Function KeyOf(Item: Pointer): Pointer; Virtual;
  270.     Function Compare(Key1, Key2: Pointer): Integer; Virtual;
  271.     Procedure FreeItem(Item: Pointer); Virtual;
  272.   End;
  273.  
  274. Function tImportCollection.KeyOf(Item: Pointer): Pointer;
  275. Begin
  276.   KeyOf:= pImportEntry(Item)^.TheName
  277. End;
  278.  
  279. Function tImportCollection.Compare(Key1, Key2: Pointer): Integer;
  280. Begin
  281.   Compare:= StrIComp(Key1, Key2)
  282. End;
  283.  
  284. Procedure TImportCollection.FreeItem(Item: Pointer);
  285. Begin
  286.   StrDispose(pImportEntry(Item)^.TheName);
  287.   StrDispose(pImportEntry(Item)^.TheDLL);
  288.   StrDispose(pImportEntry(Item)^.TheOrd);
  289.   Dispose(pImportEntry(Item))
  290. End;
  291.  
  292. Function tTypeMapCollection.KeyOf(Item: Pointer): Pointer;
  293. Begin
  294.   KeyOf:= pTypeMap(Item)^.F
  295. End;
  296.  
  297. Function tTypeMapCollection.Compare(Key1, Key2: Pointer): Integer;
  298. Begin
  299.   Compare:= StrIComp(Key1, Key2)
  300. End;
  301.  
  302. Procedure tTypeMapCollection.FreeItem(Item: Pointer);
  303. Begin
  304.   StrDispose(pTypeMap(Item)^.F);
  305.   StrDispose(pTypeMap(Item)^.T);
  306.   Dispose(pTypeMap(Item))
  307. End;
  308.  
  309. Const
  310.   TheImports: pImportCollection = Nil;
  311.   TheFuncs: pStrCollection = Nil;
  312.   TheStructs: pStrCollection = Nil;
  313.   TheTypeMap: pTypeMapCollection = Nil;
  314.   TheModMap: pStrCollection = Nil;
  315.  
  316. Procedure CreateCollections;
  317. Begin
  318.   TheImports:= New(pImportCollection, Init(100, 50));
  319.   TheFuncs:= New(pStrCollection, Init(10, 20));
  320.   TheStructs:= New(pStrCollection, Init(10, 20));
  321.   TheTypeMap:= New(pTypeMapCollection, Init(10, 10));
  322.   TheModMap:= New(pStrCollection, Init(10, 10));
  323. End;
  324.  
  325. Procedure DestroyCollections;
  326. Begin
  327.   If Assigned(TheImports) Then Dispose(TheImports, Done);
  328.   If Assigned(TheFuncs)   Then Dispose(TheFuncs,   Done);
  329.   If Assigned(TheStructs) Then Dispose(TheStructs, Done);
  330.   If Assigned(TheTypeMap) Then Dispose(TheTypeMap, Done);
  331.   If Assigned(TheModMap)  Then Dispose(TheModMap,  Done);
  332. End;
  333.  
  334. Procedure AddImport (aName, aDLL, anOrd: pChar);
  335. Var
  336.   anEntry: pImportEntry;
  337. Begin
  338.   anEntry:= New(pImportEntry);
  339.   anEntry^.TheName:= StrNew(aName);
  340.   anEntry^.TheDLL:= StrNew(aDLL);
  341.   anEntry^.TheOrd:=  StrNew(anOrd);
  342.   TheImports^.Insert(anEntry)
  343. End;
  344.  
  345. Procedure AddFunc (aName: pChar);
  346. Begin
  347.   TheFuncs^.Insert(StrNew(aName))
  348. End;
  349.  
  350. Procedure AddStruct (aName: pChar);
  351. Begin
  352.   TheStructs^.Insert(StrNew(aName))
  353. End;
  354.  
  355. Procedure AddType (aSrc, aDst: pChar);
  356. Var
  357.   anEntry: pTypeMap;
  358. Begin
  359.   anEntry:= New(pTypeMap);
  360.   anEntry^.F:= StrNew(aSrc);
  361.   anEntry^.T:= StrNew(aDst);
  362.   TheTypeMap^.Insert(anEntry)
  363. End;
  364.  
  365. Procedure AddMod (aName: pChar);
  366. Begin
  367.   TheModMap^.Insert(StrNew(aName))
  368. End;
  369.  
  370. Function GetOrdDLL (aName, RetDLL, RetOrd: pChar): Boolean;
  371. Var
  372.   Index: Integer;
  373. Begin
  374.   If TheImports^.Search(aName, Index) Then
  375.     With pImportEntry(TheImports^.At(Index))^ Do Begin
  376.       GetOrdDLL:= True;
  377.       StrCopy(RetDLL, TheDLL);
  378.       StrCopy(RetOrd, TheOrd)
  379.     End
  380.   Else
  381.     GetOrdDLL:= False
  382. End;
  383.  
  384. Procedure ReadImports (aFileName: String);
  385. Var
  386.   aFile: Text;
  387.   aLine: Array[0..500] Of Char;
  388.   aName,
  389.   aDLL,
  390.   anOrd: Array[0..60] Of Char;
  391.   aWord: Array[0..60] Of Char;
  392. Begin
  393.   {$i-} Assign(aFile, aFileName); Reset(aFile);
  394.   If IoResult<>0 Then Exit;
  395.   HasImports:= True;
  396.   StrCopy(aDLL, '?');
  397.   While Not Eof(aFile) Do Begin
  398.     GetLine(aLine, aFile);
  399.     If StrComp(ExtractWord(aWord, aLine, ' ', 1),'Library:')=0 Then
  400.       ExtractWord(aDLL, aLine, ' ', 2)
  401.     Else
  402.     If StrComp(ExtractWord(aWord, aLine, ' ', 5),'exported,')=0 Then Begin
  403.       ExtractWord(anOrd, aLine, ' ', 1);
  404.       ExtractWord(aName, aLine, ' ', 4);
  405.       AddImport(aName, aDLL, anOrd)
  406.     End
  407.   End;
  408.   Close(aFile)
  409. End;
  410.  
  411. Procedure ReadIni;
  412. Var
  413.   IniFile: Text;
  414.   aStr: String;
  415.   aLine, Word1, Word2: Array[0..255] Of Char;
  416.   rm: (rmNone, rmTypeMap, rmModMap);
  417.   p: Integer;
  418. Begin
  419.   {$i-}
  420.   Assign(IniFile, H2PasIni); Reset(IniFile);
  421.   If IoResult<>0 Then Begin
  422.     Assign(IniFile, JustPath(ParamStr(0))+'\'+H2PasIni);
  423.     Reset(IniFile);
  424.     If IoResult<>0 Then
  425.       Exit
  426.   End;
  427.   rm:= rmNone;
  428.   While Not Eof(IniFile) Do Begin
  429.     ReadLn(IniFile, aStr);
  430.     p:= Pos(';', aStr); If (p>0) Then aStr[0]:= Chr(p-1);
  431.     StrPCopy(aLine, aStr); Trim(aLine, aLine);
  432.     If StrLen(aLine)=0 Then
  433.       Continue;
  434.     If aLine[0]='[' Then Begin
  435.       If StrIComp(aLine, '[TypeMap]')=0 Then rm:= rmTypeMap Else
  436.       If StrIComp(aLine, '[ModMap]')=0 Then rm:= rmModMap Else
  437.         rm:= rmNone;
  438.       Continue
  439.     End;
  440.     Case rm Of
  441.       rmTypeMap: AddType(Trim(Word1, ExtractWord(Word1, aLine, '=', 1)),
  442.                          Trim(Word2, ExtractWord(Word2, aLine, '=', 2)));
  443.       rmModMap:  AddMod(aLine);
  444.     End
  445.   End;
  446.   Close(IniFile)
  447. End;
  448.  
  449. Function Modifier (aPart: pChar): Boolean;
  450. Var
  451.   Index: Integer;
  452. Begin
  453.   Modifier:= TheModMap^.Search(aPart, Index)
  454. End;
  455.  
  456. Function TypeConvert (aDst, aSrc: pChar): pChar;
  457. Var
  458.   aWord, ToParse: Array[0..79] Of Char;
  459.   i, anInt, anError: Integer;
  460.   aTemp: Array[0..79] Of Char;
  461.   Index: Integer;
  462. Begin
  463.   TypeConvert:= aDst;
  464.   aDst[0]:= #0;
  465.   ExtractWord(aTemp, aSrc, '[]', 2);
  466.   If StrLen(aTemp)>0 Then Begin
  467.     Val(aTemp, anInt, anError);
  468.     If anError=0 Then Begin
  469.       Str(anInt-1:0, aTemp);
  470.       StrCat(StrCat(StrCat(aDst,'Array[0..'), aTemp),'] Of ');
  471.     End Else
  472.       StrCat(StrCat(StrCat(aDst,'?'), aTemp),'?')
  473.   End;
  474.   ExtractWord(ToParse, aSrc, '[]', 1);
  475.   aTemp[0]:= #0;
  476.   For i:= 1 To WordCount(ToParse, ' ') Do Begin
  477.     ExtractWord(aWord, ToParse, ' ', i);
  478.     If aWord[0]='*' Then Begin
  479.       StrCat(aTemp,'* ');
  480.       aWord[0]:= ' ';
  481.       Trim(aWord, aWord)
  482.     End;
  483.     If (aWord[0]<>#0) And Not Modifier(aWord) Then
  484.       StrCat(StrCat(aTemp, aWord),' ');
  485.   End;
  486.  
  487.   Trim(aTemp, aTemp);
  488.   If TheTypeMap^.Search(@aTemp, Index) Then
  489.     With pTypeMap(TheTypeMap^.At(Index))^ Do
  490.       StrCopy(aTemp, T);
  491.   StrCat(aDst, aTemp)
  492. End;
  493.  
  494. Const
  495.   IdMax = 50;
  496. Type
  497.   tIdTable = Array[1..IdMax] Of
  498.     Record
  499.       TheId,
  500.       TheType: Array[0..79] Of Char;
  501.       TheComment: Array[0..300] Of Char
  502.     End;
  503. Var
  504.   IdCnt: Integer;
  505.   IdTable: tIdTable;
  506.  
  507.   Procedure InitId;
  508.   Begin
  509.     IdCnt:= 0
  510.   End;
  511.  
  512.   Procedure AddId (anId, aType, aComment: pChar);
  513.   Begin
  514.     If IdCnt=IdMax Then Begin
  515.       WriteLn('Error: Id Table full. HALT.');
  516.       Halt(1)
  517.     End;
  518.     Inc(IdCnt);
  519.     With IdTable[IdCnt] Do Begin
  520.       Trim(TheId, anId);
  521.       TypeConvert(TheType, aType);
  522.       Trim(TheComment, aComment)
  523.     End
  524.   End;
  525.  
  526.   Function ParseComment(Var Inf: Text; InStr, OutStr: pChar): Boolean;
  527.   Var
  528.     aWord: Array[0..40] Of Char;
  529.   Begin
  530.     ParseComment:= False;
  531.     If StrPos(StrLCopy(aWord, InStr, 5),'/*')=Nil Then Exit;
  532.     While StrPos(InStr, '*/')=Nil Do Begin
  533.       StrCat(OutStr, InStr);
  534.       GetLine(InStr, Inf)
  535.     End;
  536.     StrCat(OutStr, InStr);
  537.     ParseComment:= True
  538.   End;
  539.  
  540.   Function ParseDefine(InStr, OutStr: pChar): Boolean;
  541.   Const
  542.     DefineDelim = ' ';
  543.   Var
  544.     aWord: Array[0..512] Of Char;
  545.     Rest, p: pChar;
  546.     isConst: Boolean;
  547.     i: Integer;
  548.   Begin
  549.     ParseDefine:= False;
  550.     If WordCount(InStr, DefineDelim)<3 Then Exit;
  551.     If  (ExtractWord(aWord, InStr, DefineDelim, 1)<>Nil)
  552.     And (StrIComp(aWord, '#define')=0) Then Begin
  553.       isConst:= False;
  554.       If WhichBlock<>InConst Then
  555.         StrCopy(OutStr,CRLF+'Const'+CRLF+'  ')
  556.       Else
  557.         StrCopy(OutStr,'  ');
  558.       ExtractWord(StrEnd(OutStr), InStr, DefineDelim, 2);
  559.       StrCat(Pad(OutStr, OutStr, 35), '= ');
  560.       Rest:= WordPosition(InStr, DefineDelim, 3);
  561.       StrCopy(aWord, Rest);
  562.       p:= StrPos(aWord,'/*'); If Assigned(p) Then p^:= #0;
  563.       Trim(aWord, aWord);
  564.       If StrLen(aWord)>15 Then Exit;
  565.       p:= StrPos(aWord, '0x');
  566.       While Assigned(p) Do Begin
  567.         isConst:= True;
  568.         p[0]:= ' ';
  569.         p[1]:= '$';
  570.         p:= StrPos(p, '0x')
  571.       End;
  572.       p:= StrScan(aWord, 'L');  {get rid of the f*cking 'L'}
  573.       While Assigned(p) Do Begin
  574.         If (p>aWord) Then Begin
  575.           Dec(p);
  576.           If p^ In ['0'..'9','A'..'F','a'..'f'] Then Begin
  577.             p[1]:= ' ';
  578.             IsConst:= True
  579.           End;
  580.           Inc(p)
  581.         End;
  582.         p:= StrScan(p+1, 'L')
  583.       End;
  584.       If Not IsConst Then
  585.         For i:= 0 To StrLen(aWord)-1 Do
  586.           If aWord[i] In ['0'..'9'] Then Begin
  587.             IsConst:= True;
  588.             Break
  589.           End;
  590.       If Not IsConst Then
  591.         Exit;
  592.       Trim(aWord, aWord);
  593.       StrCat(StrCat(OutStr, aWord), ';');
  594.       p:= StrPos(Rest,'/*');
  595.       If Assigned(p) Then
  596.         StrCat(Pad(OutStr,OutStr, 60), p);
  597.       WhichBlock:= InConst;
  598.       ParseDefine:= True
  599.     End
  600.   End;
  601.  
  602.   Function ParseStruct(Var Inf: Text; InStr, OutStr: pChar): Boolean;
  603.   Var
  604.     aWord,
  605.     aComment,
  606.     RecComment,
  607.     RecName,
  608.     anId, aType,
  609.     Rest: Array[0..300] Of Char;
  610.     possibleArray: Array[0..60] Of Char;
  611.     p, cp: pChar;
  612.     i: Integer;
  613.   Begin
  614.     ParseStruct:= False;
  615.     If  (StrIComp(ExtractWord(aWord, Instr, ' ', 1), 'struct')<>0)
  616.     And (StrIComp(ExtractWord(aWord, Instr, ' ', 2), 'struct')<>0) Then
  617.       Exit;
  618.     p:= Instr;
  619.     Instr:= StrScan(InStr, '{');
  620.     If Not Assigned(InStr) Then Exit;
  621.  
  622.     {-try to parse the structure}
  623.     InStr^:= #0;
  624.     ExtractWord(RecName, p, ' ', WordCount(p,' '));
  625.     Inc(InStr);
  626.     Trim(InStr, InStr);
  627.     If (InStr[0]='/') And (InStr[1]='*') Then
  628.       StrCopy(RecComment, InStr)
  629.     Else
  630.       RecComment[0]:= #0;
  631.     InStr:= StrEnd(InStr);
  632.     cp:= InStr;
  633.     Repeat
  634.       GetLine(cp, Inf);
  635.       p:= StrScan(cp, '}');
  636.       cp:= StrEnd(cp);
  637.       cp^:= ' '; Inc(cp); cp^:= #0
  638.     Until Assigned(p);
  639.     If WordCount(p+1,' ;')>0 Then
  640.       ExtractWord(RecName, p+1, ' ;', 1);
  641.     pChar(p-1)^:= #0;
  642.     InitId;
  643.     p:= InStr;
  644.     Repeat
  645.       cp:= p;
  646.       p:= StrScan(p, ';');
  647.       If Assigned(p) Then Begin
  648.         Trim(aWord, ExtractWord(aWord, cp, ';', 1));
  649.         {extract possible comment}
  650.         cp:= StrPos(aWord, '/*');
  651.         If Assigned(cp) Then Begin
  652.           StrCopy(aComment, cp);
  653.           cp^:= #0
  654.         End Else
  655.           aComment[0]:= #0;
  656.         {-extract id and type}
  657.         cp:= WordPosition(aWord, ' *', WordCount(aWord, ' *')); {last word}
  658.         StrCopy(anId, cp);
  659.         ExtractWord(possibleArray, anId,'[]',2);
  660.         ExtractWord(anId, anId, '[]', 1);
  661.         cp^:= #0;
  662.         StrCopy(aType, aWord);
  663.         If StrLen(possibleArray)>0 Then
  664.           StrCat(StrCat(StrCat(aType,'['),possibleArray),']');
  665.         {-extract comment if after ';'}
  666.         Inc(p);
  667.         While p^=' ' Do Inc(p);
  668.         While (p[0]='/') And (p[1]='*') Do Begin
  669.           {append comment}
  670.           cp:= StrEnd(aComment);
  671.           Repeat
  672.             cp^:= p^;
  673.             Inc(p);
  674.             Inc(cp)
  675.           Until (p[0]=#0) Or ((p[0]='*') And (p[1]='/'));
  676.           cp[0]:= #0; StrCat(Trim(aComment, aComment),' */');
  677.           If p[0]<>#0 Then
  678.             Inc(p,2);
  679.           While p^=' ' Do Inc(p)
  680.         End;
  681.         AddId(anId, aType, aComment)
  682.       End
  683.     Until Not Assigned(p);
  684.  
  685.     {-output the structure}
  686.     If WhichBlock<>InType Then Begin
  687.       StrCopy(OutStr,CRLF+'Type'+CRLF);
  688.       OutStr:= StrEnd(OutStr)
  689.     End;
  690.     StrCopy(OutStr,'  ');
  691.     StrCat(OutStr, RecName);
  692.     StrCat(OutStr,' = Record');
  693.     If RecComment[0]<>#0 Then
  694.       StrCat(Pad(OutStr, OutStr, 40), RecComment);
  695.     StrCat(OutStr,CRLF);
  696.     For i:= 1 To IdCnt Do Begin
  697.       OutStr:= StrEnd(OutStr);
  698.       With IdTable[i] Do Begin
  699.         StrCopy(OutStr,'    ');
  700.         {If StrIComp(TheId, TheType)=0 Then StrCat(OutStr, '_');} {it works as is}
  701.         StrCat(OutStr, TheId);
  702.         If (i<IdCnt) And (StrIComp(IdTable[i].TheType, IdTable[i+1].TheType)=0) Then
  703.           StrCat(OutStr,', ')
  704.         Else Begin
  705.           StrCat(StrCat(OutStr,': '),TheType);
  706.           If i<IdCnt Then
  707.             StrCat(OutStr,'; ')
  708.         End;
  709.         If TheComment[0]<>#0 Then Begin
  710.           Pad(OutStr, OutStr, 40);
  711.           StrCat(OutStr, TheComment)
  712.         End;
  713.         StrCat(OutStr,CRLF)
  714.       End
  715.     End;
  716.     StrCat(OutStr,'  End;');
  717.     AddStruct(RecName);
  718.     WhichBlock:= InType;
  719.     ParseStruct:= True
  720.   End;
  721.  
  722.   Function ParseAPI(Var Inf: Text; InStr, OutStr: pChar): Boolean;
  723.   Var
  724.     FHead,
  725.     aWord,
  726.     Res,
  727.     FuncComment,
  728.     FuncName,
  729.     anId, aType, aComment: Array[0..200] Of Char;
  730.     p, cp, cp2, pStart: pChar;
  731.     i, Indent: Integer;
  732.     IsFunc: Boolean;
  733.     Unknown: Integer;
  734.  
  735.     Function ParseWordAndComment (aComment, aWord, Src: pChar; Delim: Char): pChar;
  736.     {parse Src, search for delim. append comments to aComment, source to aWord}
  737.     Var
  738.       cp: pChar;
  739.     Begin
  740.       Repeat
  741.         While Src^=' ' Do Inc(Src);
  742.         While (Src[0]='/') And (Src[1]='*') Do Begin
  743.           {append comment}
  744.           cp:= StrEnd(aComment);
  745.           Repeat
  746.             cp^:= Src^;
  747.             Inc(Src);
  748.             Inc(cp)
  749.           Until (Src[0]=#0) Or ((Src[0]='*') And (Src[1]='/'));
  750.           cp[0]:= #0; StrCat(Trim(aComment, aComment),' */');
  751.           If Src[0]<>#0 Then
  752.             Inc(Src,2);
  753.           While Src^=' ' Do Inc(Src)
  754.         End;
  755.         cp:= StrEnd(aWord);
  756.         While Not(Src^ In [#0,',','/']) Do Begin
  757.           cp^:= Src^; Inc(Src); Inc(cp)
  758.         End;
  759.         cp^:= #0;
  760.         If Src^=#0 Then Begin
  761.           ParseWordAndComment:= Src;
  762.           Exit
  763.         End
  764.       Until Src^=',';
  765.       Inc(Src);
  766.       While Src^=' ' Do Inc(Src);
  767.       While (Src[0]='/') And (Src[1]='*') Do Begin
  768.         {append comment}
  769.         cp:= StrEnd(aComment);
  770.         Repeat
  771.           cp^:= Src^;
  772.           Inc(Src);
  773.           Inc(cp)
  774.         Until (Src[0]=#0) Or ((Src[0]='*') And (Src[1]='/'));
  775.         cp[0]:= #0; StrCat(Trim(aComment, aComment),' */');
  776.         If Src[0]<>#0 Then
  777.           Inc(Src,2);
  778.         While Src^=' ' Do Inc(Src)
  779.       End;
  780.       ParseWordAndComment:= Src
  781.     End;
  782.  
  783.   Begin
  784.     ParseAPI:= False;
  785.     IsFunc:= False;
  786.     FuncName[0]:= #0;
  787.     Res[0]:= #0;
  788.     If (StrPos(InStr,'typedef')<>Nil)
  789.     Or (StrPos(InStr,'#define')<>Nil)
  790.     Or (StrPos(InStr,'#if')<>Nil)
  791.     Or (StrPos(InStr,'#el')<>Nil) Then Exit;
  792.     pStart:= StrScan(InStr, '(');
  793.     If Not Assigned(pStart) Then Exit;
  794.     pStart^:= #0;
  795.     Trim(FuncName, ExtractWord(FuncName, InStr, ' ', WordCount(InStr, ' ')));
  796.     cp:= WordPosition(InStr, ' ', WordCount(InStr, ' '));
  797.     If Assigned(cp) Then Begin
  798.       cp[0]:= #0;
  799.       Trim(Res, TypeConvert(Res, InStr))
  800.     End Else
  801.       StrCopy(Res, '?????');
  802.     InStr:= pStart+1;
  803.     cp:= InStr;
  804.     p:= StrScan(cp, ';');
  805.     While Not Assigned(p) Do Begin
  806.       cp:= StrEnd(cp);
  807.       cp^:= ' '; Inc(cp);
  808.       GetLine(cp, Inf);
  809.       p:= StrScan(cp, ';')
  810.     End;
  811.     StrCopy(FuncComment, p+1);
  812.     Repeat
  813.       Dec(p)
  814.     Until (p<=InStr) Or (p^=')');
  815.     p^:= #0;
  816.  
  817.     InitId;
  818.     Unknown:= 0;
  819.     p:= InStr;
  820.     While p^<>#0 Do Begin
  821.       aComment[0]:= #0;
  822.       aWord[0]:= #0;
  823.       p:= ParseWordAndComment(aComment, aWord, p, ',');
  824.       Trim(aWord, aWord);
  825.       TypeConvert(aType, aWord);
  826.       anId[0]:= #0;
  827.       cp:= WordPosition(aWord, ' *', WordCount(aWord, ' *')); {last word}
  828.       If (WordCount(aWord,' *')=1)
  829.       Or (Assigned(cp) And (StrIComp(cp, TypeConvert(aType, cp))<>0)) Then Begin
  830.       {non-Ansi declaration}
  831.         Inc(Unknown);
  832.         Str(Unknown, anId);
  833.         Move(anId[0], anId[3], StrLen(anId)+1);
  834.         anId[0]:= 'P'; anId[1]:= 'a'; anId[2]:= 'r';
  835.       End Else Begin
  836.         If Assigned(cp) Then Begin
  837.           StrCopy(anId, cp);
  838.           cp^:= #0
  839.         End;
  840.         TypeConvert(aType, aWord)
  841.       End;
  842.       AddId(anId, aType, aComment)
  843.     End;
  844.  
  845.     StrCopy(OutStr, '  Function ');
  846.     StrCat(OutStr, FuncName);
  847.     StrCat(OutStr, ' (');
  848.     Indent:= StrLen(OutStr);
  849.     OutStr:= StrEnd(OutStr);
  850.     aWord[0]:= #0;
  851.     For i:= 1 To IdCnt Do
  852.       With IdTable[i] Do Begin
  853.         StrCat(aWord, TheId);
  854.         If (i<IdCnt) And (StrIComp(IdTable[i].TheType, IdTable[i+1].TheType)=0) Then
  855.           StrCat(aWord, ', ')
  856.         Else Begin
  857.           StrCat(StrCat(aWord, ': '), TheType);
  858.           If i<IdCnt Then StrCat(aWord, '; ')
  859.         End;
  860.         Trim(aWord, aWord);
  861.         If TheComment[0]<>#0 Then
  862.           StrCat(Pad(aWord, aWord, 60-Indent), TheComment);
  863.         If (Indent+StrLen(aWord)>90) Or (TheComment[0]<>#0) Then Begin
  864.           StrCopy(OutStr, aWord); OutStr:= StrEnd(OutStr);
  865.           If i<IdCnt Then Begin
  866.             StrCat(OutStr, CRLF);
  867.             Pad(OutStr, OutStr, 2+Indent)
  868.           End;
  869.           OutStr:= StrEnd(OutStr);
  870.           aWord[0]:= #0
  871.         End
  872.       End;
  873.     StrCat(StrCat(StrCat(StrCat(StrCat(OutStr, aWord),'): '), Res),';'), FuncComment);
  874.     AddFunc(FuncName);
  875.     WhichBlock:= InFunc;
  876.     ParseAPI:= True
  877.   End;
  878.  
  879.   Procedure GenerateReport (Var Out: Text);
  880.     Procedure RepFunc (Item: Pointer); Far;
  881.     Var
  882.       aDLL, anOrd: Array[0..60] Of Char;
  883.       aLine: Array[0..200] Of Char;
  884.     Begin
  885.       StrCopy(aDLL,'?');
  886.       StrCopy(anOrd, '?');
  887.       If HasImports Then
  888.         GetOrdDLL(Item, aDLL, anOrd);
  889.       StrCat(StrCat(StrCopy(aLine,'  Function '), pChar(Item)),';');
  890.       StrCat(Pad(aLine, aLine, 42),'External ''');
  891.       StrCat(StrCat(aLine, aDLL), '''');
  892.       StrCat(Pad(aLine, aLine, 62),'Index ');
  893.       StrCat(StrCat(Pad(aLine, aLine, 72-StrLen(anOrd)), anOrd),';');
  894.       WriteLn(Out,aLine)
  895.     End;
  896.     Procedure VeriPascal (Item: Pointer); Far;
  897.     Var
  898.       aLine: Array[0..200] Of Char;
  899.       aName: Array[0..60] Of Char;
  900.     Begin
  901.       Pad(aName, Item, 35);
  902.       StrCat(StrCopy(aLine,'  veri('''), aName);
  903.       StrCat(StrCat(StrCat(aLine,''',sizeof('),aName),'));');
  904.       WriteLn(Out,aLine)
  905.     End;
  906.     Procedure VeriC (Item: Pointer); Far;
  907.     Var
  908.       aLine: Array[0..200] Of Char;
  909.       aName: Array[0..60] Of Char;
  910.     Begin
  911.       Pad(aName, Item, 35);
  912.       StrCat(StrCopy(aLine,'  veri("'), aName);
  913.       StrCat(StrCat(StrCat(aLine,'",sizeof('),aName),'));');
  914.       WriteLn(Out,aLine)
  915.     End;
  916.   Begin
  917.     WriteLn(Out, 'Implementation');
  918.     TheFuncs^.ForEach(@RepFunc);
  919.     WriteLn(Out, 'End.');
  920.     WriteLn(Out);
  921.     WriteLn(Out, '--- snip --- snip --- snip ---');
  922.     WriteLn(Out,CRLF+CRLF+'{Pascal verification program for '+Dstname+' }');
  923.     WriteLn(Out,'Program VeriP;'+CRLF+
  924.                 'Uses'+CRLF+
  925.                 '  '+DstName+';'+CRLF);
  926.     WriteLn(Out,'Procedure Veri (aStr: pChar; aSize: Integer);');
  927.     WriteLn(Out,'Begin');
  928.     WriteLn(Out,'  WriteLn(''Size of '',aStr,''= '',aSize:5);');
  929.     WriteLn(Out,'End;'+CRLF);
  930.     WriteLn(Out,'Begin');
  931.     WriteLn(Out,'  WriteLn(''verification of '+DstName+' for Pascal:'');');
  932.     TheStructs^.ForEach(@VeriPascal);
  933.     WriteLn(Out,'End.');
  934.     WriteLn(Out);
  935.     WriteLn(Out,CRLF+CRLF+'/* C verification program for '+DstName+' */');
  936.     WriteLn(Out,'#include <stdio.h>'+CRLF+
  937.                 '#include "'+DstName+'.h"'+CRLF+
  938.                 'void veri (char *aStr, int aSize)'+CRLF+
  939.                 '{ printf("Size of %s= %5i\n",aStr,aSize); }'+CRLF);
  940.     WriteLn(Out,'void main (void)'+CRLF+
  941.                 '{ printf("verification of '+DstName+' for C:\n");');
  942.     TheStructs^.ForEach(@VeriC);
  943.     WriteLn(Out,'}');
  944.   End;
  945.  
  946. Const
  947.   LineBufSize = 5000;
  948.   IoBufSize   = 32*1024;
  949. Type
  950.   IoBuf = Array[0..IoBufSize-1] Of Char;
  951.   pIoBuf = ^IoBuf;
  952. Var
  953.   Inf, Out: Text;
  954.   InStr,
  955.   OutStr: pChar;
  956. Begin
  957.   WriteLn(Version,', written 1993 by P. Sawatzki');
  958.   If Not (ParamCount In [2,3]) Then Begin
  959.     WriteLn('Usage: H2Pas InFile OutFile [ImportList]');
  960.     Halt
  961.   End;
  962.   CreateCollections;
  963.   ReadIni;
  964.   If ParamStr(3)<>'' Then
  965.     Imports:= ParamStr(3)
  966.   Else
  967.     Imports:= JustName(ParamStr(1))+'.Imp';
  968.   {$i-}
  969.   Assign(Inf, ParamStr(1)); Reset(Inf);
  970.   If IoResult<>0 Then Fatal('Input file not found');
  971.   Assign(Out, ParamStr(2)); ReWrite(Out);
  972.   If IoResult<>0 Then Fatal('Unable to create output file');
  973.   DstName:= JustName(ParamStr(2));
  974.   GetMem(InStr,  LineBufSize);
  975.   GetMem(OutStr, LineBufSize);
  976.   Write('Processing files...');
  977.   HeaderInfo(Out);
  978.   While Not Eof(Inf) Do Begin
  979.     GetLine(InStr, Inf);
  980.     OutStr[0]:= #0;
  981.     If ParseComment(Inf, InStr, OutStr)
  982.     Or ParseDefine(InStr, OutStr)
  983.     Or ParseStruct(Inf, InStr, OutStr)
  984.     Or ParseAPI(Inf, InStr, OutStr) Then
  985.       OutLn(Out, OutStr)
  986.     Else
  987.       OutLn(Out, InStr)
  988.   End;
  989.   WriteLn('Done.');
  990.   Write('Reading import file ',Imports,'...');
  991.   ReadImports(Imports);
  992.   If HasImports Then
  993.     WriteLn('Done.')
  994.   Else
  995.     WriteLn('Not found.'+CRLF+
  996.             '(generate an import file using "EXEHDR File.DLL >'+JustName(ParamStr(1))+
  997.             '.Imp")');
  998.   Write('Appending report...');
  999.   GenerateReport(Out);
  1000.   WriteLn('Done.');
  1001.   DestroyCollections;
  1002.   FreeMem(InStr,  LineBufSize);
  1003.   FreeMem(OutStr, LineBufSize);
  1004.   Close(Inf);
  1005.   Close(Out)
  1006. End.
  1007.  
  1008. { -------------  INFO ON THIS PROGRAM ------------------ }
  1009.  
  1010. ReadMe.Txt for H2Pas
  1011. ====================
  1012.  
  1013. H2Pas is a quick and dirty hack to convert C-Header files to Pascal units.
  1014.  
  1015. If you make modifications, please drop me a copy at
  1016.   Peter Sawatzki, CompuServe 100031,3002
  1017.  
  1018. In it's current implementation (1.20) H2Pas does the following:
  1019.  
  1020. - convert structs
  1021. - convert constant defines
  1022. - convert procedure/function headers
  1023. - 'convert' comments of style /* xxxx */ to { xxxx }
  1024.   and comments of style // yyyy to { yyy }
  1025. - make use of IMPort files to resolve DLL index entries
  1026. - output C and Pascal code to verify correctness of C and Pascal
  1027.   structure sizes
  1028.  
  1029. How to use and generate import files:
  1030. -------------------------------------
  1031.  
  1032. if a EXEHDR type .IMP file is present for the DLL with information
  1033. about the entry points of a function, H2Pas outputs an unit implementation
  1034. section with entries of the form:
  1035.  
  1036.   Function Ctl3DEnabled;                  External 'CTL3D'    Index    5;
  1037.  
  1038. where the appropriate indices are resolved from information gathered
  1039. from the .IMP file.
  1040.  
  1041. To generate the .IMP file for a DLL -say CTL3D.DLL- one must do the following:
  1042.  
  1043.   EXEHDR CTL3D.DLL >CTL3D.IMP
  1044.  
  1045.  
  1046. How to execute H2Pas
  1047. --------------------
  1048.  
  1049. Usage:
  1050.  
  1051. H2Pas Ctl3D.H Ctl3D.Pas [Ctl3D.Imp]
  1052.  
  1053. where Ctl3D.H is the source C header file,
  1054.       Ctl3D.Pas is the destination pascal unit to be generated
  1055.   and Ctl3D.Imp is an optional import file generated from EXEHDR
  1056.  
  1057. H2Pas.Ini
  1058. ---------
  1059.  
  1060. currently H2Pas.Ini has two areas for customization:
  1061.  
  1062. [TypeMap]
  1063. C-Type = Pascal-Type
  1064.  
  1065. maps a certain C-type to a Pascal type (see sample H2Pas.Ini)
  1066.  
  1067. [ModMap]
  1068. modifier
  1069.  
  1070. a list of modifiers that H2Pas should ignore (see sample H2Pas.Ini)
  1071.  
  1072. written by
  1073.  
  1074.   Peter Sawatzki
  1075.   Buchenhof 3
  1076.   58091 Hagen / Germany
  1077.   CompuServe: 100031,3002
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  { ------------------  SAMPLE INI FILE NEED FOR THIS UNIT ---------- }
  1084.  { CUT and Save as H2PAS.INI                                         }
  1085.  
  1086. [TypeMap]
  1087. unsigned        = Word
  1088. unsigned int    = Word
  1089. char            = Char
  1090. unsigned long   = LongInt
  1091. int             = Integer
  1092. char far *      = pChar
  1093. unsigned char   = Byte
  1094. byte            = Byte
  1095. char *          = pChar
  1096. long            = LongInt
  1097. WORD            = Word
  1098. DWORD           = LongInt
  1099. ULONG           = LongInt
  1100. BOOL            = Bool
  1101. UINT            = Word
  1102. void *          = Pointer
  1103. ; Windows stuff
  1104. BITMAPINFO      = tBitmapInfo
  1105. HANDLE          = tHandle
  1106. HWINDOW         = hWindow
  1107. COLORREF        = tColorRef
  1108.  
  1109. [ModMap]
  1110. WINAPI
  1111. WINGAPI
  1112. APIENTRY
  1113. EXPENTRY
  1114. EXPORT
  1115. EXTERN
  1116. PASCAL
  1117. FAR
  1118. _FAR
  1119. const
  1120.  
  1121.